package it.pir.es06ChatRMIPull;

import java.net.MalformedURLException;
import java.rmi.*;
import java.rmi.server.*;
import java.util.*;
public class ChatImpl extends UnicastRemoteObject implements Chat{

	private static final long serialVersionUID = 1L;
	private static final int MAXSIZE = 100;
	private static final int DELETEDMESSAGES = MAXSIZE/10;
	private SortedMap<Integer,Message> messageBox;
	private int lastId;
	
	public ChatImpl() throws RemoteException{
		/* Viene creata una SortedMap perch� in questo modo siamo in grado
		 * di ricevere dal client un id e di estrapolare a partire da questo id, la sottolista ordinata.
		 * Usare una Map classica non ci garantiva tale ordine.
		 */
		messageBox = new TreeMap<Integer,Message>();
		lastId = 0;
	}
	
	
	public static void main(String arg[]) throws RemoteException, MalformedURLException{
		
		//Il main crea un oggetto di tale classe e lo registra all'rmiregistry
		ChatImpl chat=new ChatImpl();
		Naming.rebind("chat",chat);
		
	}
	
	@Override
	//Tale metodo � sincronizzato perch� si accede alla struttura condivisa messageBox
	public synchronized void send(Message msg) throws RemoteException {
		/*
		 * Non appena un client invia un messaggio, prepara l'oggetto message ma lascia l'id dell'oggetto inalterato a -1 mentre la variabile
		 * lastId locale del client viene incrementata. Il server, invece, mantiene in locale un lastId che enumera i vari messaggi di tutta la conversazione
		 * quindi considerando i msg di tutti i client. Non appena arriva un oggetto message, il server incrementa il suo campo id di uno e aggiorna la sua variabile
		 * lastId locale.
		 */
		msg.setId(++lastId);
		
		//Si inserisce nella Map ordinata il valore dell'id e l'oggetto message
		messageBox.put(lastId,msg);
		
		
		if(messageBox.size()>MAXSIZE){
			
			//Creo un iteratore sull'insieme delle chiavi
			Iterator<Map.Entry<Integer,Message>> it = messageBox.entrySet().iterator();
			
			//Cancelliamo il 10% dei messaggi pi� vecchi
			for(int i = 0; i < DELETEDMESSAGES; i++){
				it.next();
				it.remove();
			}
		}
	}

	@Override
	public synchronized List<Message> receive(int lastId) throws RemoteException {
		
		//Estrapolo la sottolista-tailMap
		Map<Integer,Message> m = messageBox.tailMap(lastId+1);
		
		//Poi ritorno solo una LinkedList dei valori
		return new LinkedList<Message>(m.values());
	}
	
}
